package com.warmheart.base.filter;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Map;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.support.StandardServletMultipartResolver;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.warmheart.base.config.SysConfig.Sign;
import com.warmheart.base.executor.TraceContext;
import com.warmheart.core.enums.ResultCode;
import com.warmheart.core.result.CommonResult;
import com.warmheart.core.util.JsonResponseUtil;
import com.warmheart.core.util.rsa.RsaSignUtil;

/**
 * 
 * @ClassName: SignFilter
 * @Description: 签名过滤器
 * @author ZhangJianyang
 * @date 2025-06-16 09:37:02
 *
 */
public abstract class SignFilter implements Filter {

    private static Logger logger = LoggerFactory.getLogger(SignFilter.class);

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
            ServletException {
        if (!sign().getParam().getStatus() && !sign().getResult().getStatus()) {
            chain.doFilter(request, response);
            return;
        }
        Date startTime = new Date();
        String preSpanId = TraceContext.getSpan();
        TraceContext.setSpan();
        logger.info("----------------------------签名处理开始----------------------------");
        try {
            if (request instanceof HttpServletRequest) {
                HttpServletRequest hRequest = (HttpServletRequest) request;
                HttpServletResponse hResponse = (HttpServletResponse) response;
                // 这里只处理POST请求
                if (hRequest.getMethod().equalsIgnoreCase("post")) {
                    ObjectMapper mapper = new ObjectMapper();
                    SignRequestWrapper requestWrapper = null;
                    if (sign().getParam().getStatus()) {
                        String contentType = hRequest.getContentType();
                        if (StringUtils.isNotBlank(contentType) && contentType.contains("multipart/form-data")) {
                            // 将转化后的 request 放入过滤链中
                            hRequest = new StandardServletMultipartResolver().resolveMultipart(hRequest);
                        }
                        requestWrapper = new SignRequestWrapper(hRequest);
                        BufferedReader br = new BufferedReader(new InputStreamReader(hRequest.getInputStream(),
                                StandardCharsets.UTF_8));
                        String line;
                        StringBuilder sb = new StringBuilder();
                        while ((line = br.readLine()) != null) {
                            sb.append(line);
                        }
                        String param = sb.toString();
                        logger.info("请求数据：" + param);
                        if (StringUtils.isBlank(param)) {
                            JsonResponseUtil.writerJsonFromObj(hResponse,
                                    CommonResult.failed(ResultCode.PARAM_JSON_CONVERT_INVALID, "参数不完整"));
                            return;
                        }
                        Map<String, Object> paramMap = mapper.readValue(param,
                                new TypeReference<Map<String, Object>>() {
                                });
                        if (paramMap == null || paramMap.isEmpty()) {
                            JsonResponseUtil.writerJsonFromObj(hResponse,
                                    CommonResult.failed(ResultCode.PARAM_JSON_CONVERT_INVALID, "参数不完整"));
                            return;
                        }
                        Object signObj = paramMap.get("sign");
                        if (signObj == null) {
                            JsonResponseUtil.writerJsonFromObj(hResponse,
                                    CommonResult.failed(ResultCode.PARAM_JSON_CONVERT_INVALID, "参数不完整"));
                            return;
                        }
                        String sign = signObj.toString();
                        if (StringUtils.isBlank(sign)) {
                            JsonResponseUtil.writerJsonFromObj(hResponse,
                                    CommonResult.failed(ResultCode.PARAM_JSON_CONVERT_INVALID, "参数不完整"));
                            return;
                        }
                        Object dataObj = paramMap.get("data");
                        if (dataObj == null) {
                            JsonResponseUtil.writerJsonFromObj(hResponse,
                                    CommonResult.failed(ResultCode.PARAM_JSON_CONVERT_INVALID, "参数不完整"));
                            return;
                        }
                        String dataStr = mapper.writeValueAsString(dataObj);
                        Map<String, Object> dataMap = mapper.readValue(dataStr,
                                new TypeReference<Map<String, Object>>() {
                                });
                        if (dataMap == null || dataMap.isEmpty()) {
                            JsonResponseUtil.writerJsonFromObj(hResponse,
                                    CommonResult.failed(ResultCode.PARAM_JSON_CONVERT_INVALID, "参数不完整"));
                            return;
                        }
                        // 验签
                        String signStr = null;
                        try {
                            // signStr = RsaSignUtil.sortMapByKey(dataMap);
                        } catch (Exception e) {
                            JsonResponseUtil.writerJsonFromObj(hResponse, CommonResult.failed(ResultCode.ERROR_SERVER));
                            return;
                        }
                        boolean verifyResult = RsaSignUtil.verify(signStr, sign, null, "UTF-8");
                        if (!verifyResult) {
                            JsonResponseUtil.writerJsonFromObj(hResponse, CommonResult.failed(ResultCode.SIGN_INVALID));
                            return;
                        }
                        // 校验时间戳
                        // 移除时间戳
                        dataMap.remove("timeStamp");
                        // 移除随机字符串
                        dataMap.remove("nostr");
                        String requestBody = mapper.writeValueAsString(dataMap);
                        logger.info("真正的参数数据：" + requestBody);
                        requestWrapper.setRequestBody(requestBody);
                    }
                    if (sign().getResult().getStatus()) {
                        SignResponseWrapper responseWrapper = new SignResponseWrapper(hResponse);
                        if (sign().getParam().getStatus()) {
                            chain.doFilter(requestWrapper, responseWrapper);
                        } else {
                            chain.doFilter(hRequest, responseWrapper);
                        }
                        if (responseWrapper.getStatus() == 200) {
                            String resp = responseWrapper.getTextContent();
                            // logger.info("加密前返回数据：" + resp);
                            // // 加密处理返回
                            // String srcStr = AESUtil.toEncryptParam(resp,
                            // secKey);
                            // logger.info("返回数据加密完成");
                            // logger.info("加密后返回数据：" + srcStr);
                            // // 重新解密(保持调试数据正常)
                            // String resourceStr =
                            // AESUtil.toDecryptParam(srcStr,
                            // secKey);
                            JsonResponseUtil.writerJsonStr(hResponse, resp);
                        }
                    } else {
                        if (sign().getParam().getStatus()) {
                            chain.doFilter(requestWrapper, hResponse);
                        } else {
                            chain.doFilter(hRequest, hResponse);
                        }
                    }
                } else {
                    chain.doFilter(hRequest, hResponse);
                }
            } else {
                chain.doFilter(request, response);
            }
        } catch (Exception e) {
            logger.error("签名滤器处理失败：" + e.getMessage(), e);
        } finally {
            Long nextSpanCost = TraceContext.getSpanCost();
            Date endTime = new Date();
            Long currSpanCost = endTime.getTime() - startTime.getTime() - nextSpanCost;
            logger.info("签名处理耗时{}ms", currSpanCost);
            logger.info("----------------------------签名处理结束----------------------------");
            TraceContext.resetSpanCost(endTime.getTime() - startTime.getTime());
            TraceContext.resetSpan(preSpanId);
        }
    }

    /**
     * 
     * @Title: sign
     * @Description: 验签签名配置
     * @author ZhangJianyang
     * @return
     */
    protected abstract Sign sign();
}
